import configparser
from datetime import datetime
import os
import pickle

from selenium import webdriver
from selenium.webdriver import DesiredCapabilities
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import time

from selenium.webdriver.support.wait import WebDriverWait

from src.Logging import Logging

cfg = configparser.RawConfigParser()
conf_path = "../config.conf"
cfg.read([conf_path], encoding='utf-8')

WIDTH = 375
HEIGHT = 812
PIXEL_RATIO = 3.0
UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1'

logger = Logging(__name__).get_logger()

class DaMai(object):
    def __init__(self):
        # 首页url
        self.damai_url = "https://www.damai.cn/"
        # 登录界面
        self.login_url = "https://passport.damai.cn/login?ru=https%3A%2F%2Fwww.damai.cn%2F"
        # 购票界面url
        self.book_url = cfg.get("ticket_info", "book_url").strip()

        self.price_list = cfg.get("ticket_info", "price").strip().split(",")  # 抢票的价格挡位，从左向右
        self.price = list(map(int, self.price_list))
        self.times_list = cfg.get("ticket_info", "times").strip().split(",")
        self.times = list(map(int, self.times_list))
        self.ticket_num = int(cfg.get("ticket_info", "ticket_num").strip())
        self.ticket_num_name = int(cfg.get("ticket_info", "ticket_num_name").strip())
        self.driver_path = cfg.get("other", "driver_path").strip()

        self.status = 0  # 是否登录的状态 0是未登录，1是登录

        self.current_num = 1  # 当前抢票第几次
        self.num = int(cfg.get("ticket_info", "num").strip())  # 抢票总次数

        self.datetime = cfg.get("ticket_info", "date_time").strip()  # 抢票时间点
        self.rush_time = time.strptime(self.datetime, '%Y-%m-%d %H:%M:%S')
        self.countdown = None
        # 设置无头浏览器 无界面浏览器
        self.chrome_options = webdriver.ChromeOptions()
        # 设置默认编码为utf-8，也就是中文
        self.chrome_options.add_argument('lang=zh_CN.UTF-8')
        # 禁止硬件加速
        self.chrome_options.add_argument('--disable-gpu')
        # 取消沙盒模式
        self.chrome_options.add_argument('--no-sandbox')
        # 禁止弹窗广告
        self.chrome_options.add_argument('--disable-popup-blocking')
        # 去掉反扒标志
        self.chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
        # 此方法针对V78版本及以上有效，同时可以解决部分网站白屏的问题。
        self.chrome_options.add_experimental_option('useAutomationExtension', False)
        # ##大量渲染时候写入/tmp而非/dev/shm
        self.chrome_options.add_argument("-–disable-dev-shm-usage")
        desired_capabilities = DesiredCapabilities.CHROME
        desired_capabilities["pageLoadStrategy"] = "none"
        # # 忽略证书错误（实操没卵用）
        # self.chrome_options.add_argument('--ignore-certificate-errors')

        # 保存浏览历史下次读取直接读取里面的内容
        # dir_path = os.getcwd()
        # self.chrome_options.add_argument(f'user-data-dir={dir_path}/userData')

        mobileEmulation = {"deviceMetrics": {"width": WIDTH, "height": HEIGHT, "pixelRatio": PIXEL_RATIO},
                           "userAgent": UA}
        self.chrome_options.add_experimental_option("mobileEmulation", mobileEmulation)

        self.driver = webdriver.Chrome(executable_path=self.driver_path, chrome_options=self.chrome_options)  # 此项稳定版打开
        # self.driver = webdriver.Chrome(executable_path=self.driver_path)  # 默认谷歌浏览器, 指定下驱动的位置
        # self.driver = webdriver.Chrome()  # 默认谷歌浏览器
        with open('../stealth.min.js') as f:
            js = f.read()
        self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": js
        })
        # 将window.navigator.webdriver属性变为undefined 防止检测
        # 修改get方法
        script = 'Object.defineProperty(navigator, "webdriver", {get:()=>undefined,});'
        # execute_cdp_cmd用来执行chrome开发这个工具命令
        self.driver.execute_script(script)

        self.driver.set_window_size(400, 900)

    def quit(self):
        self.driver.quit()

    def login(self):
        if not os.path.exists('cookies.pkl'):  # 如果不存在cookie.pkl,就登录获取一下
            self.get_cookie()
        else:  # 存在就设置下cookie
            self.driver.get(self.damai_url)
            self.set_cookie()

    def get_cookie(self):
        try:
            # 先进入登录页面进行登录
            logger.info("------开始登录------")
            self.driver.get(self.login_url)
            iframe = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.ID, 'alibaba-login-box')))
            self.driver.switch_to.frame(0)
            login_methods = self.driver.find_elements(By.CLASS_NAME, 'login-tabs-tab')
            login_methods[2].click()

            logger.info("------请扫码------")

            while (self.driver.title != '大麦网-全球演出赛事官方购票平台-100%正品、先付先抢、在线选座！' and self.driver.title != '大麦'):
                time.sleep(1)
            logger.info("------扫码成功------")
            pickle.dump(self.driver.get_cookies(), open("cookies.pkl", "wb"))
            logger.info("------Cookie保存成功------")
        except Exception as e:
            logger.exception(e)
            raise e

    def set_cookie(self):
        try:
            cookies = pickle.load(open("cookies.pkl", "rb"))  # 载入cookie
            for cookie in cookies:
                cookie_dict = {
                    'domain': '.damai.cn',  # 必须有，不然就是假登录
                    'name': cookie.get('name'),
                    'value': cookie.get('value'),
                    "expires": "",
                    'path': '/',
                    'httpOnly': False,
                    'HostOnly': False,
                    'Secure': False}
                self.driver.add_cookie(cookie_dict)
            logger.info('------载入Cookie------')
        except Exception as e:
            logger.exception("------cookie 设置失败，原因：%s------" % e)

    def select_times(self):
        try:
            choose_price = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'bui-dm-sku-module')))

            ## 选择场次
            choose_price_times = WebDriverWait(choose_price, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "sku-times-card")))
            times_list = choose_price_times.find_elements(By.CLASS_NAME, "bui-dm-sku-card-item")

            logger.info("------演出场次数量：%s------" % len(times_list))
            if len(times_list) != 1:
                num = 0
                for i in self.times:
                    try:
                        times_text = times_list[i - 1].find_element(By.CLASS_NAME, "item-tag-outer").find_element(
                            By.CLASS_NAME, "item-tag").text
                        if times_text == '无票':
                            logger.warning("------第 %s 场次票已经售完------" % i)
                            num += 1
                            if num < len(self.times):
                                continue
                    except:
                        logger.warning("------第 %s 场次票已经售完------" % i)
                        num += 1
                        if num < len(self.times):
                            continue
                    else:
                        js = "document.querySelector('body > div.bui-modal.sku-pop > div:nth-child(2) > div > div > div > div > div.bui-dm-sku-card.sku-times-card > div.sku-content > div.bui-dm-sku-card-item:nth-child(%s) > div.item-content > div').click()" % i
                        self.driver.execute_script(js)
                        logger.info('已选择 %s 场次' % times_list[i - 1].text)
                        break
        except Exception as e:
            logger.exception('选择场次报错: %s ' % e)
            raise e
        else:
            # 选择票档
            self.select_price()

    def select_price(self):
        try:
            choose_price = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'bui-dm-sku-module')))

            ## 选择票档
            choose_price_tickets = WebDriverWait(choose_price, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "sku-tickets-card")))
            tickets_list = choose_price_tickets.find_elements(By.CLASS_NAME, "bui-dm-sku-card-item")

            logger.info("------票价档次数量：%s------" % len(tickets_list))
            num = 0
            for i in self.price:
                try:
                    logger.info("------正在抢购第 %s 挡位票------" % i)
                    span = tickets_list[i - 1].find_element(By.CLASS_NAME, 'item-tag-outer')
                    logger.warning("------第 %s 档票已经售完------" % i)
                    num += 1
                    if num < len(self.price):
                        continue
                except:
                    js = "document.querySelector('body > div.bui-modal.sku-pop > div:nth-child(2) > div > div > div > div > div.bui-dm-sku-card.sku-tickets-card > div.sku-content').children[%s].click()" % (i - 1)
                    # webdriver.ActionChains(self.driver).move_to_element(tickets_list[i - 1]).click(
                    #     tickets_list[i - 1]).perform()
                    self.driver.execute_script(js)
                    logger.info('已选择第 %s 挡位票' % i)
                    break
            if num == len(self.price):
                logger.warning("------你想抢的票已售完------")
                raise Exception("你想抢的票已售完")
        except Exception as e:
            logger.exception('选择票档报错: %s ' % e)
            raise e
        else:
            # 增加票数量
            self.select_number()

    def select_number(self):
        try:
            # 增加票数量
            choose_price_footer = WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CLASS_NAME, 'bui-dm-sku-counter')))
            num = self.ticket_num - 1

            for i in range(num):
                js = "document.querySelector('body > div.bui-modal.sku-pop > div:nth-child(2) > div > div > div > div > div.bui-dm-sku-footer.theme-normal > div.bui-dm-sku-counter > div.number-edit > div:nth-child(3)').click()"
                self.driver.execute_script(js)
                logger.info('已加选 %s 张票' % (i + 1))

            choose_price_footer_bottom = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'sku-footer-bottom')))
            choose_price_footer_buy_button = choose_price_footer_bottom.find_element(By.CLASS_NAME,
                                                                                     'sku-footer-buy-button')
            if choose_price_footer_buy_button.text != '确定' and choose_price_footer_buy_button.text != '特惠购买':
                logger.warning("------你想抢的票暂不可售------")
                raise Exception("你想抢的票暂不可售")
            js2 = "document.querySelector('body > div.bui-modal.sku-pop > div:nth-child(2) > div > div > div > div > div.bui-dm-sku-footer.theme-normal > div.sku-footer-bottom > div.bui-btn.bui-btn-contained.bui-btn-medium.sku-footer-buy-button.half-width.normal.sku-footer-buy-button').click()"
            self.driver.execute_script(js2)
            # webdriver.ActionChains(self.driver).move_to_element(choose_price_footer_buy_button).click(choose_price_footer_buy_button).perform()
            logger.info('已点击购买 前往订单确认页')
        except Exception as e:
            logger.exception('增加票数量报错: %s ' % e)
            raise e
        else:
        #     # 选择购买人
            self.select_buy_name()

    def select_buy_name(self):
        try:
            buy_name_label = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.ID, 'dmViewerBlock_DmViewerBlock')))
            buy_name_list = buy_name_label.find_elements(By.XPATH, "//div[@class='viewer']/div/div")
            for i in range(self.ticket_num_name):
                try:
                    weixuan = buy_name_list[i].find_element(By.CLASS_NAME, 'icondanxuan-weixuan_')
                    logger.info("------%s 未选中------" % buy_name_list[i].text)

                    js2 = "document.getElementsByClassName('icondanxuan-weixuan_')[%s].click()" % 0
                    self.driver.execute_script(js2)
                except Exception as e:
                    logger.exception('选择观演人失败：%s' % e)
        except Exception as e:
            logger.exception(e)
            raise e
        else:
            # 提交订单
            self.submit()

    def submit(self):
        try:
            submit_click = self.driver.find_element(By.XPATH, "//div[@class='tpl-wrapper']/div[@view-name='LinearLayout']/div[@view-name='LinearLayout']/div[@view-name='FrameLayout']/div[@view-name='TextView']")
            click_2 = True
            while click_2:
                if submit_click.text == '提交订单':
                    logger.info('提交订单')
                    submit_click.click()
                    # js = "document.querySelector('#dmOrderSubmitBlock_DmOrderSubmitBlock > div:nth-child(2) > div > div:nth-child(2) > div:nth-child(3) > div:nth-child(2)').click()"
                    # self.driver.execute_script(js)
                time.sleep(2)
                if self.driver.title == '支付宝付款':
                    click_2 = False
                if self.driver.title == "订单确认页":
                    raise Exception("---失败，重试---")
        except Exception as e:
            logger.exception(e)
            raise e

    def open_page(self):
        try:

            # 刷新页面
            self.driver.refresh()

            # 直接来到演唱会购票界面
            self.driver.get(self.book_url)

            # 判断抢票时间是否到达
            # print("------等待抢票时间点到来，进行抢票------")
            # while time.mktime(self.rush_time) - time.time() > 5:  # 提前0.2-0.5秒开始抢
            #     time.sleep(0.1)

            # 点击立即预定
            click_book = WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CLASS_NAME, "buy__button__text")))

            b = True
            while b:
                if click_book.text != '' and click_book.text != '缺货登记':
                    b = False
                if click_book.text == '':
                    continue
                # 刷新页面
                if click_book.text == '缺货登记':
                    logger.warning('缺货登记')
                    self.driver.refresh()
                    click_book = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "buy__button__text")))

            while True:
                try:
                    count_down = self.driver.find_element(By.ID, 'bottom').find_element(By.CLASS_NAME, 'count-down')
                    countdown = count_down.find_element(By.CLASS_NAME, 'countdown').text
                    if self.countdown != countdown:
                        self.countdown = countdown
                        print(self.countdown)
                except Exception as e:
                    self.driver.refresh()
                    break

            while True:
                try:
                    click_book = WebDriverWait(self.driver, 0.5).until(
                        EC.presence_of_element_located((By.CLASS_NAME, "buy__button__text")))

                    if click_book.text == '即将开抢':
                        self.driver.refresh()
                        continue

                    if click_book.text != '立即预订' and click_book.text != '立即购买' and click_book.text != '特惠购买':
                        if click_book.text != '' and click_book.text == '缺货登记':
                            self.driver.refresh()
                        continue
                    else:
                        try:
                            click_book_des = self.driver.find_element(By.CLASS_NAME, "buy__button__des")
                            if time.mktime(self.rush_time) - time.time() <= 1:
                                self.driver.refresh()
                                continue
                        except Exception as ex:
                            logger.info("----------开始抢票----------")
                            break
                except Exception as e:
                    self.driver.refresh()
                    print('刷新页面')

            js2 = "document.querySelector('#bottom > div.detail-bar > div.button-outline > div.detail-button > div > div > div > p').click()"
            self.driver.execute_script(js2)

        except Exception as e:
            logger.exception(e)
            raise e


    # def rush_ticket(self):
    #     try:
    #
    #         # 选择场次
    #         self.select_times()
    #
    #     except Exception as e:
    #         logger.exception(e)
    #         raise e

    def run(self):
        try:
            # 登录
            self.login()

            start_time = time.time()
            logger.info("------准备抢票，时间点：%s------" % datetime.now())
            # 抢票
            loop = 1
            i = 0
            while True:
                try:
                    # 打开抢票页面
                    self.open_page()
                    logger.info("------正在进行第 %s 轮抢票------" % (i + 1))
                    # 选择场次
                    self.select_times()
                    break
                except Exception as e:
                    logger.exception(e)
                    if loop == self.num:
                        raise e
                    if str(e) != '你想抢的票已售完' and str(e) != '失败，重试':
                        loop += 1
                    i += 1
                    pass

            end_time = time.time()
            logger.info("抢票结束，时间点：%s" % datetime.now())
            logger.info("抢票总时长：%s， 此时长不包括登录时间" % (end_time - start_time))
            logger.info("抢票成功，抓紧去订单中付款！！")

            time.sleep(600)
            # 关闭浏览器
            # self.quit()

        except Exception as e:
            time.sleep(600)
            # self.driver.quit()
            logger.exception("******抢票失败，原因：%s******" % e)

if __name__ == '__main__':
    damai = DaMai()
    damai.run()